// Monaco Editor 实例管理器
// 实现编辑器实例的创建、销毁和复用机制，优化内存使用，支持多文件编辑

import * as monaco from 'monaco-editor';
import { Tab, TabStatus } from '../stores/tabStore';

// 编辑器实例接口
export interface EditorInstance {
  id: string;
  editor: monaco.editor.IStandaloneCodeEditor;
  model: monaco.editor.ITextModel;
  tabId: string;
  filePath: string;
  language: string;
  isActive: boolean;
  lastUsed: number;
  memoryUsage: number;
}

// 编辑器池配置
export interface EditorPoolConfig {
  maxInstances: number;        // 最大实例数量
  maxInactiveTime: number;     // 最大非活动时间（毫秒）
  memoryThreshold: number;     // 内存阈值（MB）
  enableModelReuse: boolean;   // 是否启用模型复用
  enableLazyLoading: boolean;  // 是否启用懒加载
  gcInterval: number;          // 垃圾回收间隔（毫秒）
}

// 默认配置
const DEFAULT_CONFIG: EditorPoolConfig = {
  maxInstances: 10,
  maxInactiveTime: 5 * 60 * 1000, // 5分钟
  memoryThreshold: 100, // 100MB
  enableModelReuse: true,
  enableLazyLoading: true,
  gcInterval: 30 * 1000, // 30秒
};

// 编辑器实例管理器
export class EditorInstanceManager {
  private instances = new Map<string, EditorInstance>();
  private modelCache = new Map<string, monaco.editor.ITextModel>();
  private config: EditorPoolConfig;
  private gcTimer: NodeJS.Timeout | null = null;
  private container: HTMLElement | null = null;

  constructor(config: Partial<EditorPoolConfig> = {}) {
    this.config = { ...DEFAULT_CONFIG, ...config };
    this.startGarbageCollection();
  }

  // 设置编辑器容器
  setContainer(container: HTMLElement) {
    this.container = container;
  }

  // 创建或获取编辑器实例
  async getOrCreateInstance(tab: Tab): Promise<EditorInstance> {
    const existingInstance = this.instances.get(tab.id);
    
    if (existingInstance) {
      existingInstance.lastUsed = Date.now();
      existingInstance.isActive = true;
      return existingInstance;
    }

    // 检查实例数量限制
    if (this.instances.size >= this.config.maxInstances) {
      await this.cleanupOldInstances();
    }

    return this.createInstance(tab);
  }

  // 创建新的编辑器实例
  private async createInstance(tab: Tab): Promise<EditorInstance> {
    if (!this.container) {
      throw new Error('Editor container not set');
    }

    // 尝试复用模型
    let model = this.getOrCreateModel(tab);
    
    // 创建编辑器实例
    const editor = monaco.editor.create(this.container, {
      model,
      theme: 'vs-dark',
      automaticLayout: true,
      minimap: { enabled: false },
      scrollBeyondLastLine: false,
      wordWrap: 'on',
      fontSize: 14,
      lineNumbers: 'on',
      renderWhitespace: 'selection',
      tabSize: 2,
      insertSpaces: true,
    });

    // 计算内存使用量
    const memoryUsage = this.calculateMemoryUsage(model);

    const instance: EditorInstance = {
      id: `editor_${tab.id}`,
      editor,
      model,
      tabId: tab.id,
      filePath: tab.filePath,
      language: tab.language,
      isActive: true,
      lastUsed: Date.now(),
      memoryUsage,
    };

    // 设置事件监听器
    this.setupInstanceEventListeners(instance, tab);

    this.instances.set(tab.id, instance);
    return instance;
  }

  // 获取或创建模型
  private getOrCreateModel(tab: Tab): monaco.editor.ITextModel {
    if (this.config.enableModelReuse) {
      const cachedModel = this.modelCache.get(tab.filePath);
      if (cachedModel && !cachedModel.isDisposed()) {
        // 更新模型内容
        if (cachedModel.getValue() !== tab.content) {
          cachedModel.setValue(tab.content);
        }
        return cachedModel;
      }
    }

    // 创建新模型
    const uri = monaco.Uri.file(tab.filePath);
    let model = monaco.editor.getModel(uri);
    
    if (!model) {
      model = monaco.editor.createModel(tab.content, tab.language, uri);
    } else {
      // 更新现有模型
      if (model.getValue() !== tab.content) {
        model.setValue(tab.content);
      }
    }

    if (this.config.enableModelReuse) {
      this.modelCache.set(tab.filePath, model);
    }

    return model;
  }

  // 设置实例事件监听器
  private setupInstanceEventListeners(instance: EditorInstance, tab: Tab) {
    const { editor, model } = instance;

    // 监听内容变化
    model.onDidChangeContent(() => {
      instance.lastUsed = Date.now();
      // 这里可以触发标签页状态更新
      this.notifyContentChange(instance, model.getValue());
    });

    // 监听光标位置变化
    editor.onDidChangeCursorPosition((e) => {
      instance.lastUsed = Date.now();
      this.notifyCursorPositionChange(instance, e.position);
    });

    // 监听选择变化
    editor.onDidChangeCursorSelection((e) => {
      instance.lastUsed = Date.now();
      this.notifySelectionChange(instance, e.selection);
    });

    // 监听滚动变化
    editor.onDidScrollChange((e) => {
      instance.lastUsed = Date.now();
      this.notifyScrollChange(instance, e.scrollTop, e.scrollLeft);
    });
  }

  // 激活编辑器实例
  activateInstance(tabId: string): EditorInstance | null {
    const instance = this.instances.get(tabId);
    if (!instance) return null;

    // 隐藏所有其他实例
    this.instances.forEach((inst, id) => {
      inst.isActive = id === tabId;
      if (inst.isActive) {
        inst.editor.getDomNode()?.style.setProperty('display', 'block');
        inst.editor.focus();
        inst.lastUsed = Date.now();
      } else {
        inst.editor.getDomNode()?.style.setProperty('display', 'none');
      }
    });

    return instance;
  }

  // 更新实例内容
  updateInstanceContent(tabId: string, content: string): boolean {
    const instance = this.instances.get(tabId);
    if (!instance) return false;

    if (instance.model.getValue() !== content) {
      instance.model.setValue(content);
      instance.lastUsed = Date.now();
    }

    return true;
  }

  // 更新实例语言
  updateInstanceLanguage(tabId: string, language: string): boolean {
    const instance = this.instances.get(tabId);
    if (!instance) return false;

    monaco.editor.setModelLanguage(instance.model, language);
    instance.language = language;
    instance.lastUsed = Date.now();

    return true;
  }

  // 销毁编辑器实例
  destroyInstance(tabId: string): boolean {
    const instance = this.instances.get(tabId);
    if (!instance) return false;

    // 清理编辑器
    instance.editor.dispose();

    // 如果不启用模型复用，也清理模型
    if (!this.config.enableModelReuse) {
      instance.model.dispose();
      this.modelCache.delete(instance.filePath);
    }

    this.instances.delete(tabId);
    return true;
  }

  // 获取实例
  getInstance(tabId: string): EditorInstance | null {
    return this.instances.get(tabId) || null;
  }

  // 获取所有实例
  getAllInstances(): EditorInstance[] {
    return Array.from(this.instances.values());
  }

  // 获取活动实例
  getActiveInstance(): EditorInstance | null {
    return Array.from(this.instances.values()).find(inst => inst.isActive) || null;
  }

  // 计算内存使用量
  private calculateMemoryUsage(model: monaco.editor.ITextModel): number {
    const content = model.getValue();
    const sizeInBytes = new Blob([content]).size;
    return sizeInBytes / (1024 * 1024); // 转换为MB
  }

  // 获取总内存使用量
  getTotalMemoryUsage(): number {
    return Array.from(this.instances.values())
      .reduce((total, instance) => total + instance.memoryUsage, 0);
  }

  // 清理旧实例
  private async cleanupOldInstances(): Promise<void> {
    const now = Date.now();
    const instancesToRemove: string[] = [];

    this.instances.forEach((instance, tabId) => {
      if (!instance.isActive && 
          (now - instance.lastUsed) > this.config.maxInactiveTime) {
        instancesToRemove.push(tabId);
      }
    });

    // 如果还是超过限制，移除最旧的非活动实例
    if (instancesToRemove.length === 0 && this.instances.size >= this.config.maxInstances) {
      const sortedInstances = Array.from(this.instances.entries())
        .filter(([_, instance]) => !instance.isActive)
        .sort(([_, a], [__, b]) => a.lastUsed - b.lastUsed);

      if (sortedInstances.length > 0) {
        instancesToRemove.push(sortedInstances[0][0]);
      }
    }

    // 移除实例
    for (const tabId of instancesToRemove) {
      this.destroyInstance(tabId);
    }
  }

  // 启动垃圾回收
  private startGarbageCollection(): void {
    this.gcTimer = setInterval(() => {
      this.cleanupOldInstances();
      
      // 检查内存使用量
      const totalMemory = this.getTotalMemoryUsage();
      if (totalMemory > this.config.memoryThreshold) {
        console.warn(`Editor memory usage (${totalMemory.toFixed(2)}MB) exceeds threshold`);
        this.cleanupOldInstances();
      }
    }, this.config.gcInterval);
  }

  // 停止垃圾回收
  private stopGarbageCollection(): void {
    if (this.gcTimer) {
      clearInterval(this.gcTimer);
      this.gcTimer = null;
    }
  }

  // 销毁管理器
  destroy(): void {
    this.stopGarbageCollection();
    
    // 销毁所有实例
    this.instances.forEach((_, tabId) => {
      this.destroyInstance(tabId);
    });

    // 清理模型缓存
    this.modelCache.forEach(model => {
      if (!model.isDisposed()) {
        model.dispose();
      }
    });
    this.modelCache.clear();
  }

  // 事件通知方法（可以被外部覆盖）
  public notifyContentChange(instance: EditorInstance, content: string): void {
    // 默认实现为空，可以被子类或外部覆盖
  }

  public notifyCursorPositionChange(instance: EditorInstance, position: monaco.Position): void {
    // 默认实现为空
  }

  public notifySelectionChange(instance: EditorInstance, selection: monaco.Selection): void {
    // 默认实现为空
  }

  public notifyScrollChange(instance: EditorInstance, scrollTop: number, scrollLeft: number): void {
    // 默认实现为空
  }
}

// 单例实例
let editorInstanceManager: EditorInstanceManager | null = null;

// 获取编辑器实例管理器
export const getEditorInstanceManager = (config?: Partial<EditorPoolConfig>): EditorInstanceManager => {
  if (!editorInstanceManager) {
    editorInstanceManager = new EditorInstanceManager(config);
  }
  return editorInstanceManager;
};

// 重置编辑器实例管理器
export const resetEditorInstanceManager = (): void => {
  if (editorInstanceManager) {
    editorInstanceManager.destroy();
    editorInstanceManager = null;
  }
};
